#include "SbotMainWindow.h"

#include <QBuffer>
#include <QPainter>

SbotMainWindow::SbotMainWindow(QWindow* parent) : QQuickWindow(parent) {
    this->setMinimumSize(QSize(840, 580));
    this->setFlags(flags() | Qt::WindowType::Window | Qt::WindowType::FramelessWindowHint);
    this->SetWindowsStyle();
}

void SbotMainWindow::SetWindowsStyle() {
    auto hwnd = reinterpret_cast<HWND>(this->winId());
    DWORD style = GetWindowLong(hwnd, GWL_STYLE);

    SetWindowLong(hwnd, GWL_STYLE, style | WS_THICKFRAME | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX);
    const MARGINS shadow = {1, 1, 1, 1};
    ::DwmExtendFrameIntoClientArea(hwnd, &shadow);
}

bool SbotMainWindow::nativeEvent(const QByteArray& eventType, void* message, qintptr* result) {
    MSG* msg = reinterpret_cast<MSG*>(message);

    switch (msg->message) {
        case WM_NCCALCSIZE: {
            *result = 0;
            return true;
        }
        case WM_NCHITTEST: {
            QPoint mousePos(GET_X_LPARAM(msg->lParam), GET_Y_LPARAM(msg->lParam));
            *result = AdjustResizeWindow(msg->hwnd, mousePos);
            if (*result != 0) {
                return true;
            } else {
                return false;
            }
        }
        default: return QWindow::nativeEvent(eventType, message, result);
    }
}

bool SbotMainWindow::event(QEvent* event) {
    if (event->type() == QEvent::Type::WindowStateChange) {
        if (this->windowStates() & Qt::WindowState::WindowMaximized) {
            this->AdjustWindowContentMarginsWhenMaximized(true);
        } else {
            this->AdjustWindowContentMarginsWhenMaximized(false);
        }
    }

    return QQuickWindow::event(event);
}

int SbotMainWindow::AdjustResizeWindow(HWND hwnd, const QPoint& mousePos) {
    RECT windowRect = {0, 0, 0};
    int result = 0;
    bool allowResizeWidth = this->minimumWidth() != this->maximumWidth();
    bool allowResizeHeight = this->minimumHeight() != this->maximumHeight();
    int mouseX = mousePos.x();
    int mouseY = mousePos.y();

    ::GetWindowRect(hwnd, &windowRect);

    if (allowResizeWidth) {
        if (mouseX >= windowRect.left && mouseX < windowRect.left + RESIZE_EDGE_THRESHOLD) {
            result = HTLEFT;
        } else if (mouseX <= windowRect.right && mouseX > windowRect.right - RESIZE_EDGE_THRESHOLD) {
            result = HTRIGHT;
        }
    }

    if (allowResizeHeight) {
        if (mouseY >= windowRect.top && mouseY < windowRect.top + RESIZE_EDGE_THRESHOLD) {
            result = HTTOP;
        } else if (mouseY <= windowRect.bottom && mouseY > windowRect.bottom - RESIZE_EDGE_THRESHOLD) {
            result = HTBOTTOM;
        }
    }

    if (allowResizeWidth && allowResizeHeight) {
        if (mouseX >= windowRect.left && mouseX < windowRect.left + RESIZE_EDGE_THRESHOLD && mouseY >= windowRect.top &&
            mouseY < windowRect.top + RESIZE_EDGE_THRESHOLD) {
            result = HTTOPLEFT;
        } else if (mouseX <= windowRect.right && mouseX > windowRect.right - RESIZE_EDGE_THRESHOLD &&
                   mouseY >= windowRect.top && mouseY < windowRect.top + RESIZE_EDGE_THRESHOLD) {
            result = HTTOPRIGHT;
        }
        if (mouseX >= windowRect.left && mouseX < windowRect.left + RESIZE_EDGE_THRESHOLD &&
            mouseY <= windowRect.bottom && mouseY > windowRect.bottom - RESIZE_EDGE_THRESHOLD) {
            result = HTBOTTOMLEFT;
        } else if (mouseX <= windowRect.right && mouseX > windowRect.right - RESIZE_EDGE_THRESHOLD &&
                   mouseY <= windowRect.bottom && mouseY > windowRect.bottom - RESIZE_EDGE_THRESHOLD) {
            result = HTBOTTOMRIGHT;
        }
    }

    return result;
}

void SbotMainWindow::AdjustWindowContentMarginsWhenMaximized(bool isMaximized) {
    auto contentItem = this->contentItem();
    auto childItems = contentItem->childItems();

    if (!childItems.isEmpty()) {
        auto contentLayout = childItems.first();
        if (isMaximized) {
            RECT frame = {0, 0, 0, 0};
            ::AdjustWindowRectEx(&frame, WS_OVERLAPPEDWINDOW, FALSE, 0);

            frame.left = std::abs(frame.right);
            frame.top = std::abs(frame.bottom);
            double pixelRatio = this->devicePixelRatio();

            QMetaObject::invokeMethod(contentLayout, "adjustWindowContentMarginsWhenMaximized",
                                      Q_ARG(QVariant, static_cast<int>(frame.left / pixelRatio)),
                                      Q_ARG(QVariant, static_cast<int>(frame.right / pixelRatio)),
                                      Q_ARG(QVariant, static_cast<int>(frame.top / pixelRatio)),
                                      Q_ARG(QVariant, static_cast<int>(frame.bottom / pixelRatio)));
        } else {
            QMetaObject::invokeMethod(contentLayout, "adjustWindowContentMarginsWhenMaximized", Q_ARG(QVariant, 0),
                                      Q_ARG(QVariant, 0), Q_ARG(QVariant, 0), Q_ARG(QVariant, 0));
        }
    }
}

int SbotMainWindow::LoadPlugin(int pluginIndex) {
    if (this->curPluginViewId == pluginIndex) {
        return SBT_ERROR;
    }

    // Get Plugin qml object
    QObject* pluginQmlObject = this->pluginManger.GetPluginUi(pluginIndex);
    if (!pluginQmlObject) {
        qDebug() << "Get plugin qml object faild!";
        return SBT_ERROR;
    }

    QObject* pluginDetail = this->findChild<QObject*>("pluginDetail");


    if (pluginDetail) {
        // Insert the plugin QML component as a child item to the main window
        QQuickItem* pluginDetailItem = qobject_cast<QQuickItem*>(pluginDetail);
        QQuickItem* pluginQmlItem = qobject_cast<QQuickItem*>(pluginQmlObject);

        if (pluginDetailItem && pluginQmlItem) {
            if (this->curPluginQmlItem == nullptr) {
                pluginQmlItem->setParentItem(pluginDetailItem);
                this->curPluginQmlItem = pluginQmlItem;
            } else if (this->curPluginQmlItem != pluginQmlItem) {
                this->curPluginQmlItem->setParentItem(nullptr);  //卸载界面
                pluginQmlItem->setParentItem(pluginDetailItem);
                this->curPluginQmlItem = pluginQmlItem;
            } else {
                return SBT_NERR;
            }
        } else {
            qDebug() << "Error! Failed to cast main window or plugin QML object to QQuickItem";
            return SBT_ERROR;
        }
    } else {
        qDebug() << "Not find pluginDetail component!";
        return SBT_ERROR;
    }

    this->pluginManger.StartPluginThread(pluginIndex);
    this->curPluginViewId = pluginIndex;
    return SBT_NERR;
}

void SbotMainWindow::RefreshPluginListView() {
    int icnt = 0;
    QObject* pluginLists = this->findChild<QObject*>("pluginLists");

    if (!pluginLists) {
        qWarning() << "Failed to find pluginLists object in QML";
        return;
    }

    for (; icnt < this->pluginManger.GetPluginNum(); icnt++) {
        const QIcon& icon = this->pluginManger.GetPluginLogo(icnt);

        // Convert QIcon to QImage
        QSize size(32, 32);  // Assuming a standard icon size of 64x64
        QImage image(size, QImage::Format_ARGB32);
        image.fill(Qt::transparent);  // Using transparent background
        QPainter painter(&image);
        icon.paint(&painter, QRect(QPoint(0, 0), size));

        // Convert QImage to Base64
        QByteArray byteArray;
        QBuffer buffer(&byteArray);
        buffer.open(QIODevice::WriteOnly);
        image.save(&buffer, "PNG");  // Saving image as PNG
        QString base64Image = QString::fromLatin1(byteArray.toBase64().data());

        // Append to model
        QVariantMap newElement;
        newElement["name"] = this->pluginManger.GetPluginName(icnt);
        newElement["pluginId"] = icnt;
        newElement["selected"] = false;
        newElement["iconsrc"] = "data:image/png;base64," + base64Image;

        QVariant returnedValue;
        QMetaObject::invokeMethod(pluginLists, "addElement", Q_ARG(QVariant, QVariant::fromValue(newElement)));
    }
}

void SbotMainWindow::mouseDoubleClickEvent(QMouseEvent* event) {
    // 使用 position() 获取鼠标位置
    QPoint mousePos = event->position().toPoint();

    // 检查鼠标双击是否发生在标题栏区域
    if (mousePos.y() <= TITLE_BAR_HEIGHT) {
        // 如果窗口目前是最大化的，那么还原它
        if (this->windowState() & Qt::WindowMaximized) {
            this->showNormal();
        } else {
            // 否则最大化窗口
            this->showMaximized();
        }
    }
}

void SbotMainWindow::showEvent(QShowEvent* event) {
    QQuickWindow::showEvent(event);
    this->pluginManger.RefreshPlugin(PLUGIN_PATH);                 // 刷新插件池
    this->pluginManger.InitAllPlugin(qmlContext(this)->engine());  // 初始化所有插件
}

void SbotMainWindow::windowsExit() { this->pluginManger.StopPluginThreadAll(); }

void SbotMainWindow::onPluginListLoaded() {
    this->RefreshPluginListView();  //刷新插件列表视图
}

void SbotMainWindow::onPluginDetailLoaded() {
    this->LoadPlugin(DEFAULT_PLUGIN_INDEX);  // 加载默认插件
}

void SbotMainWindow::swPluginView(int pluginId) { this->LoadPlugin(pluginId); }
